import '../file_node.dart';
import 'fs_gateway.dart';
import 'path_resolver.dart';
import 'package:path/path.dart' as p;

/// [RenameService]：文件/文件夹重命名服务。
///
/// 功能职责：
/// - 将逻辑路径与节点解析为真实路径；
/// - 生成目标的新路径；
/// - 检查是否存在同名冲突；
/// - 调用 [FileSystemGateway] 执行重命名操作。
///
/// 架构说明：
/// - 与 [CreateService] / [DeleteService] 保持一致的结构；
/// - 依赖 [PathResolver] 进行路径解析；
/// - 依赖 [FileSystemGateway] 执行底层文件系统操作。
///
/// 使用示例：
/// ```dart
/// final service = RenameService(
///   pathResolver: PathResolver(),
///   fs: LocalFileSystemGateway(),
/// );
///
/// final success = await service.rename(
///   logicalPath: '/projects/demo',
///   node: FileNode(name: 'old.dart', isFolder: false),
///   newName: 'new.dart',
/// );
///
/// if (success) {
///   print('重命名成功');
/// } else {
///   print('重命名失败（可能是同名冲突或路径解析失败）');
/// }
/// ```
class RenameService {
  /// 路径解析器：负责将逻辑路径转换为真实路径。
  final PathResolver pathResolver;

  /// 文件系统网关：封装底层文件操作。
  final FileSystemGateway fs;

  RenameService({required this.pathResolver, required this.fs});

  /// 根据逻辑路径与节点，以及新名称，执行重命名操作。
  ///
  /// - [logicalPath] 树状视图中的逻辑路径（如 `/src/utils`）；
  /// - [node] 目标 [FileNode]（表示文件或文件夹）；
  /// - [newName] 新的名称（不含父路径，只是文件/文件夹名）；
  ///
  /// 返回值：
  /// - `true` → 重命名成功；
  /// - `false` → 失败（路径解析失败、同名冲突等）。
  ///
  /// 内部逻辑：
  /// 1. 使用 [PathResolver] 解析旧的真实路径；
  /// 2. 拼接出新的目标路径（同父目录下的新名字）；
  /// 3. 检查是否已存在同名文件/文件夹 → 若存在返回 `false`；
  /// 4. 调用 [FileSystemGateway.renameFile] 或 [FileSystemGateway.renameDir] 执行操作。
  Future<bool> rename({
    required String logicalPath,
    required FileNode node,
    required String newName,
  }) async {
    // 解析“旧”的真实路径
    final oldReal = pathResolver.resolve(logicalPath, node);
    if (oldReal.isEmpty) return false;

    final parent = p.dirname(oldReal);
    final newReal = p.normalize(p.join(parent, newName));

    // 同名冲突检查
    if (node.isFolder) {
      if (await fs.existsDir(newReal) || await fs.existsFile(newReal)) {
        return false;
      }
      await fs.renameDir(oldReal, newReal);
    } else {
      if (await fs.existsFile(newReal) || await fs.existsDir(newReal)) {
        return false;
      }
      await fs.renameFile(oldReal, newReal);
    }

    return true;
  }
}
